﻿#include "init.h"

int gge_searcher(lua_State *L) {
	
	lua_getfield(L, lua_upvalueindex(1), "searchpath");//package.searchpath
	lua_rotate(L,-2,-1);
	lua_getfield(L, lua_upvalueindex(1), "path");//package.path

	lua_call(L,2,-1);

	if (lua_isstring(L,1)){
		luaL_loadfile(L, lua_tostring(L,1));
		lua_rotate(L,-2,-1);
		return 2;
	}else{
		lua_remove(L,-2);
	}

	return 1;
}

int gge_getscript(lua_State *L) {
	
//	Utf8_Ansi(L);
	lua_getfield(L, lua_upvalueindex(1), "searchpath");//package.searchpath
	lua_rotate(L,-2,-1);
	lua_getfield(L, lua_upvalueindex(1), "path");//package.path

	lua_call(L,2,-1);

	if (lua_isstring(L,1)){
		size_t nr;
		luaL_Buffer b;
		FILE *f = fopen(lua_tostring(L,-1), "r");
		luaL_buffinit(L, &b);
		do {  /* read file in chunks of LUAL_BUFFERSIZE bytes */
			char *p = luaL_prepbuffer(&b);
			nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f);
			luaL_addsize(&b, nr);
		} while (nr == LUAL_BUFFERSIZE);
		luaL_pushresult(&b);  /* close buffer */
		fclose(f);
		return 1;
	}

	return 0;
}


#include "SDL.h"

static const char *getnextfilename (char **path, char *end) {
    char *sep;
    char *name = *path;
    if (name == end)
        return NULL;  /* no more names */
    else if (*name == '\0') {  /* from previous iteration? */
        *name = *LUA_PATH_SEP;  /* restore separator */
        name++;  /* skip it */
    }
    sep = strchr(name, *LUA_PATH_SEP);  /* find next separator */
    if (sep == NULL)  /* separator not found? */
        sep = end;  /* name goes until the end */
    *sep = '\0';  /* finish file name */
    *path = sep;  /* will start next search from here */
    return name;
}

int gge_require(lua_State* L) {
    const char *module = lua_tostring(L, 1);
    Sint64 size = 0;
    char *chunk = NULL;
    SDL_RWops * ops = NULL;

    const char *search = NULL, *filename = NULL;
    char *pathname = NULL, *endpathname = NULL;

    lua_getglobal(L, LUA_LOADLIBNAME);	                // push "package"
    lua_getfield(L, -1, "path");				    // push "package.path"
    lua_remove(L, -2);								// remove "package"

    search = luaL_checkstring(L, -1);
    lua_pop(L, 2);

    if (strchr(module, '.') != NULL)
        module = luaL_gsub(L, module, ".", LUA_DIRSEP);  /* replace it by 'dirsep' */


    luaL_Buffer buff;
    luaL_buffinit(L, &buff);
    luaL_addgsub(&buff, search, LUA_PATH_MARK, module);
    luaL_addchar(&buff, '\0');

    pathname = luaL_buffaddr(&buff);  /* writable list of file names */
    endpathname = pathname + luaL_bufflen(&buff) - 1;

    while ((filename = getnextfilename(&pathname, endpathname)) != NULL) {

        ops = SDL_RWFromFile(filename, "rb");

        if (ops) {
            break;
        }
    }

    if (ops) {      //文件打开成功
        size = SDL_RWsize(ops);
        chunk = malloc(size + 1);

        SDL_RWread(ops, chunk, size, size + 1);

        chunk[size] = 0;

        SDL_RWclose(ops);

        luaL_loadbuffer(L, chunk, size, module);

        free(chunk);
    }

    return 1;
}


void gge_addLoader(lua_State *L, int (*FUNC)(lua_State* L)){
    lua_getglobal(L, LUA_LOADLIBNAME);	// push "package"
    lua_getfield(L, -1, "searchers");				// push "package.loaders"
    lua_remove(L, -2);								// remove "package"
    // Count the number of entries in package.loaders.
    // Table is now at index -2, since 'nil' is right on top of it.
    // lua_next pushes a key and a value onto the stack.
    int numLoaders = 0;
    lua_pushnil(L);
    while (lua_next(L, -2) != 0) 	{
        lua_pop(L, 1);
        numLoaders++;
    }
    lua_pushinteger(L, numLoaders + 1);
    lua_pushcfunction(L, FUNC);
    lua_rawset(L, -3);	// Table is still on the stack.  Get rid of it now.
    lua_pop(L, 1);
}



int gge_init (lua_State *L) {
    const char *path = luaL_checkstring(L, -1);
    lua_pop(L, 1);

	lua_getglobal(L,LUA_LOADLIBNAME);
	lua_getfield(L, -1, "searchers");

	lua_pushvalue(L,-2);
	lua_pushcclosure(L, gge_searcher,1);
	lua_seti(L, -2, 2);
	lua_pop(L,1);

//	GetRunPath(L);
    lua_pushstring(L, ".");

	luaL_gsub(L,"?.lua;lua/?.lua;!/lua/?.lua;script/?.lua;!/script/?.lua;!/lua/?/?.lua;lua/?/?.lua",LUA_EXEC_DIR,lua_tostring(L,-1));
	lua_setfield(L,-3,"path");
	char cpath[1024] = {0};
	sprintf(cpath, "?.so;lib/?.so;!/?.so;!/lib/?.so;%s/lib?.so", path);
    luaL_gsub(L, cpath, LUA_EXEC_DIR, lua_tostring(L,-1));
	lua_setfield(L,-3,"cpath");

	lua_pop(L,2);

    gge_addLoader(L, gge_require);

	return 0;
}